﻿using System;
using System.Data;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using GSF.TimeSeries.Transport;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace SIEGateCoreTest.AclTests
{
    /// <summary>
    /// Summary description for AclTests
    /// </summary>
    [TestClass]
    public class AclTests
    {
        private DataSet m_dataSource;
        private Guid m_subscriberID;
        private Guid[] m_signalIDs;

        public AclTests()
        {
            DataRow row;

            m_dataSource = new DataSet();
            m_subscriberID = Guid.NewGuid();
            m_signalIDs = Enumerable.Range(0, 16).Select(i => Guid.NewGuid()).ToArray();

            m_dataSource.Tables.Add(new DataTable("SubscriberMeasurements"));
            m_dataSource.Tables.Add(new DataTable("SubscriberMeasurementGroups"));
            m_dataSource.Tables.Add(new DataTable("MeasurementGroupMeasurements"));

            m_dataSource.Tables["SubscriberMeasurements"].Columns.Add("SubscriberID");
            m_dataSource.Tables["SubscriberMeasurements"].Columns.Add("SignalID");
            m_dataSource.Tables["SubscriberMeasurements"].Columns.Add("Allowed");
            m_dataSource.Tables["SubscriberMeasurementGroups"].Columns.Add("SubscriberID");
            m_dataSource.Tables["SubscriberMeasurementGroups"].Columns.Add("MeasurementGroupID");
            m_dataSource.Tables["SubscriberMeasurementGroups"].Columns.Add("Allowed");
            m_dataSource.Tables["MeasurementGroupMeasurements"].Columns.Add("MeasurementGroupID");
            m_dataSource.Tables["MeasurementGroupMeasurements"].Columns.Add("SignalID");

            // Create group for implicitly allowed measurements
            row = m_dataSource.Tables["SubscriberMeasurementGroups"].NewRow();
            row["SubscriberID"] = m_subscriberID;
            row["MeasurementGroupID"] = 1;
            row["Allowed"] = 1;
            m_dataSource.Tables["SubscriberMeasurementGroups"].Rows.Add(row);

            // Create group for implicitly denied measurements
            row = m_dataSource.Tables["SubscriberMeasurementGroups"].NewRow();
            row["SubscriberID"] = m_subscriberID;
            row["MeasurementGroupID"] = 0;
            row["Allowed"] = 0;
            m_dataSource.Tables["SubscriberMeasurementGroups"].Rows.Add(row);

            for (int i = 0; i < m_signalIDs.Length; i++)
            {
                Guid signalID = m_signalIDs[i];
                bool explicitlyAllowed = Convert.ToBoolean(i & 8);
                bool explicitlyDenied = Convert.ToBoolean(i & 4);
                bool implicitlyAllowed = Convert.ToBoolean(i & 2);
                bool implicitlyDenied = Convert.ToBoolean(i & 1);

                if (explicitlyAllowed)
                {
                    // Add record for explicitly allowed measurement
                    row = m_dataSource.Tables["SubscriberMeasurements"].NewRow();
                    row["SubscriberID"] = m_subscriberID;
                    row["SignalID"] = signalID;
                    row["Allowed"] = 1;
                    m_dataSource.Tables["SubscriberMeasurements"].Rows.Add(row);
                }

                if (explicitlyDenied)
                {
                    // Add record for explicitly denied measurement
                    row = m_dataSource.Tables["SubscriberMeasurements"].NewRow();
                    row["SubscriberID"] = m_subscriberID;
                    row["SignalID"] = signalID;
                    row["Allowed"] = 0;
                    m_dataSource.Tables["SubscriberMeasurements"].Rows.Add(row);
                }

                if (implicitlyAllowed)
                {
                    // Add record for implicitly allowed measurement
                    row = m_dataSource.Tables["MeasurementGroupMeasurements"].NewRow();
                    row["MeasurementGroupID"] = 1;
                    row["SignalID"] = signalID;
                    m_dataSource.Tables["MeasurementGroupMeasurements"].Rows.Add(row);
                }

                if (implicitlyDenied)
                {
                    // Add record for implicitly denied measurement
                    row = m_dataSource.Tables["MeasurementGroupMeasurements"].NewRow();
                    row["MeasurementGroupID"] = 0;
                    row["SignalID"] = signalID;
                    m_dataSource.Tables["MeasurementGroupMeasurements"].Rows.Add(row);
                }
            }
        }

        [TestMethod]
        public void TestGetAuthorizedSignals()
        {
            UnsynchronizedClientSubscription.AdapterInfo info = new UnsynchronizedClientSubscription.AdapterInfo();
            ISet<Guid> authorizedSignals = info.GetAuthorizedSignals(m_dataSource, m_subscriberID);

            for (int i = 0; i < m_signalIDs.Length; i++)
            {
                Guid signalID = m_signalIDs[i];
                bool explicitlyAllowed = Convert.ToBoolean(i & 8);
                bool explicitlyDenied = Convert.ToBoolean(i & 4);
                bool implicitlyAllowed = Convert.ToBoolean(i & 2);
                bool implicitlyDenied = Convert.ToBoolean(i & 1);

                bool allowed = !explicitlyDenied && (explicitlyAllowed || (!implicitlyDenied && implicitlyAllowed));
                bool authorized = authorizedSignals.Contains(signalID);

                Assert.AreEqual(allowed, authorized, string.Format("Test failed for: {0}{1}{2}{3}", (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1));
            }
        }

        [TestMethod]
        public void TestSubscriberHasRights()
        {
            UnsynchronizedClientSubscription.AdapterInfo info = new UnsynchronizedClientSubscription.AdapterInfo();

            for (int i = 0; i < m_signalIDs.Length; i++)
            {
                Guid signalID = m_signalIDs[i];
                bool explicitlyAllowed = Convert.ToBoolean(i & 8);
                bool explicitlyDenied = Convert.ToBoolean(i & 4);
                bool implicitlyAllowed = Convert.ToBoolean(i & 2);
                bool implicitlyDenied = Convert.ToBoolean(i & 1);

                bool allowed = !explicitlyDenied && (explicitlyAllowed || (!implicitlyDenied && implicitlyAllowed));
                bool authorized = info.SubscriberHasRights(m_dataSource, m_subscriberID, signalID);

                Assert.AreEqual(allowed, authorized, string.Format("Test failed for: {0}{1}{2}{3}", (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1));
            }
        }
    }
}
